package com.wooming.myserver.config;

import com.wooming.myserver.filter.JwtAuthenticationFilter;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;

/**
 * Spring Security 配置类
 *
 * @author Kimi&Wooming 2025/05/22
 */
@Configuration // 表明这是一个配置类
@EnableWebSecurity // 启用 Web 安全支持
public class SecurityConfig {

    // 定义 SecurityFilterChain Bean 来配置安全规则
    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
        // 开始配置安全规则
        return http
                // 配置请求授权规则
                .authorizeHttpRequests(auth -> auth
                        // 配置允许匿名访问的请求路径。这里可以根据你的项目需求添加更多的公开路径
                        .requestMatchers("/api/public/**").permitAll()
                        .requestMatchers("/public/**").permitAll()
                        // 配置需要认证的请求路径
                        .requestMatchers("/api/**").authenticated()
                        // 其他路径默认允许所有访问
                        .anyRequest().permitAll()
                )
                // 配置会话管理
                .sessionManagement(session -> session
                        // 设置会话创建策略为无状态。因为我们使用 JWT 进行无状态认证，所以不需要 Spring Security 创建会话
                        .sessionCreationPolicy(SessionCreationPolicy.STATELESS)
                )
                // 添加自定义的 JWT 认证过滤器到过滤器链中，并指定它在 UsernamePasswordAuthenticationFilter 之前执行
                .addFilterBefore(new JwtAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class)
                // 禁用 CSRF。因为我们使用的是 RESTful API，通常不会使用传统的表单提交，所以可以禁用 CSRF 保护
                .csrf(AbstractHttpConfigurer::disable)
                .build();
    }
}
